#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include <simple_protocol.h>
#include <simple_protocol_impl.h>

#include <iostream>

namespace py = pybind11;

static void initialize_module()
{
    // std::cout << "hello simple protocol!" << std::endl;
}

static void exit_module()
{
    // std::cout << "simple protocol cleaning up!" << std::endl;
}

PYBIND11_MODULE(simple_protocol, m)
{
    m.doc() = R"(Here is a simple protocol module for Python that supports a configurable communication protocol function. The protocol format is as follows: [SYNC_HEADER | FRAME_LEN | CHANNEL | DATA | CRC16].

- SYNC_HEADER: Synchronization Header
- FRAME_LEN: Frame Length, describing the length of the data for CHANNEL + DATA + CRC16
- CHANNEL: Channel, used to distinguish different types of data
- DATA: The data that the user needs to send
- CRC16: When this feature is enabled, CRC16 is used for verification)";

    py::enum_<SimpleProtocolImpl::FrameStatus>(m, "FrameStatus")
        .value("BUFFER_EMPTY", SimpleProtocolImpl::FrameStatus::BUFFER_EMPTY, "The buffer is empty.")
        .value("BUFFER_INVALID", SimpleProtocolImpl::FrameStatus::BUFFER_INVALID, "The buffer is invalid.")
        .value("BUFFER_TIMEOUT", SimpleProtocolImpl::FrameStatus::BUFFER_TIMEOUT, "The buffer is timeout.")
        .value("BUFFER_BROKEN", SimpleProtocolImpl::FrameStatus::BUFFER_BROKEN, "The buffer is broken.")
        .value("BUFFER_NOT_ENOUGH", SimpleProtocolImpl::FrameStatus::BUFFER_NOT_ENOUGH, "The buffer is not enough.")
        .value("LENGTH_NOT_ENOUGH", SimpleProtocolImpl::FrameStatus::LENGTH_NOT_ENOUGH, "The length of the frame is not enough.")
        .value("LENGTH_ERROR", SimpleProtocolImpl::FrameStatus::LENGTH_ERROR, "The length of the frame is invalid.")
        .value("CRC_ERROR", SimpleProtocolImpl::FrameStatus::CRC_ERROR, "The CRC of the frame is invalid.")
        .value("INVALID", SimpleProtocolImpl::FrameStatus::INVALID, "The frame is invalid.")
        .value("VALID", SimpleProtocolImpl::FrameStatus::VALID, "The frame is valid.");

    py::class_<SimpleProtocolImpl::frame_t>(m, "Frame")
        .def(py::init<SimpleProtocolImpl::FrameStatus, uint32_t, std::vector<uint8_t>>())
        .def("str_data", &SimpleProtocolImpl::frame_t::str_data, "Convert the saved data into a string.")
        .def_readwrite("status", &SimpleProtocolImpl::frame_t::status)
        .def_readwrite("channel", &SimpleProtocolImpl::frame_t::channel)
        .def_readwrite("data", &SimpleProtocolImpl::frame_t::data);

    py::class_<SimpleProtocolImpl>(m, "SimpleProtocolImpl")
        // 数据处理辅助函数
        .def("curr_timestamp_ms", &SimpleProtocolImpl::curr_timestamp_ms, "Get current time in milliseconds.")
        // 包解析相关函数
        .def("buffer_is_empty", &SimpleProtocolImpl::buffer_is_empty, "Check if the buffer is empty.")
        .def("buffer_flush", &SimpleProtocolImpl::buffer_flush, "Flush the buffer.")

        .def("push_back", py::overload_cast<const uint8_t *, const size_t>(&SimpleProtocolImpl::push_back), "Push a buffer into the buffer.")
        .def("push_back", py::overload_cast<const std::vector<uint8_t> &>(&SimpleProtocolImpl::push_back), "Push a vector of bytes into the buffer.")
        // .def("push_back", py::overload_cast<const uint8_t>(&SimpleProtocolImpl::push_back), "Push a vector of bytes into the buffer.")
        // .def("push_back", py::overload_cast<const uint16_t>(&SimpleProtocolImpl::push_back), "Push a vector of bytes into the buffer.")
        // .def("push_back", py::overload_cast<const uint32_t>(&SimpleProtocolImpl::push_back), "Push a vector of bytes into the buffer.")
        // .def("push_back", py::overload_cast<const uint64_t>(&SimpleProtocolImpl::push_back), "Push a vector of bytes into the buffer.")

        .def("parse", py::overload_cast<>(&SimpleProtocolImpl::parse), "Parse the buffer and return a frame.")
        .def("parse", py::overload_cast<const std::vector<uint8_t> &>(&SimpleProtocolImpl::parse), "Parse the buffer and return a frame.")
        .def("parse_until_valid", &SimpleProtocolImpl::parse_until_valid, "Parse the buffer and try get one valid farme.")
        .def("parse_n", &SimpleProtocolImpl::parse_n, "Parse the buffer and return n frame.")
        .def("parse_all", &SimpleProtocolImpl::parse_all, "Parse the buffer and return all frame.")
        .def("can_parsed", &SimpleProtocolImpl::can_parsed, "Determine whether there is still data that needs to be parsed based on the status of the last parsed data.")

        // 打包相关函数
        .def("pack", py::overload_cast<const void *, const size_t, const uint32_t>(&SimpleProtocolImpl::pack), "Pack a buffer into a frame.")
        .def("pack", py::overload_cast<const std::vector<uint8_t> &, const uint32_t>(&SimpleProtocolImpl::pack), "Pack a vector of bytes into a frame.")
        .def("pack", py::overload_cast<const std::string &, const uint32_t>(&SimpleProtocolImpl::pack), "Pack a string into a frame.");

    // m.def("crc16", py::overload_cast<const void *, size_t>(&SimpleProtocolImpl::crc16), "Calculate CRC16 of a buffer", py::arg("buffer"), py::arg("buffer_length"));
    // m.def("crc16", py::overload_cast<const std::vector<uint8_t> &>(&SimpleProtocolImpl::crc16), "Calculate CRC16 of a vector of bytes", py::arg("data"));

    py::class_<SimpleProtocol, SimpleProtocolImpl>(m, "SimpleProtocol")
        .def(py::init<std::vector<uint8_t>, const uint8_t, const uint8_t, const bool, const uint32_t, const uint32_t>());

    initialize_module(); // 模块被导入时执行初始化

    atexit(exit_module); // 模块被卸载时执行清理工作
}
